package xkp.lesson1;

import javafx.scene.transform.Scale;

import javax.sound.midi.Receiver;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.Scanner;
import java.util.concurrent.CopyOnWriteArrayList;

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(55555);
        //并发集合，高效的线程安全，在多线程中放心大胆使用
        CopyOnWriteArrayList<Socket> sockets = new CopyOnWriteArrayList<>();
        //需要两条线程
        //1、启动子线程等待客户端连接
        //此处使用的是Lambda表达式
 /*       new Thread(() -> {

        }).start();*/
 //1.1 class MyThread extends Thread{ public void run(){} }
/* new Thread(){
     @Override
     public void run() {
         super.run();
     }
 }.start();*/
//1.2
/*
        class MyRunnable implements Runnable{

            @Override
            public void run() {

            }
        }

        new Thread(new MyRunnable()).start();
*/

/*        new Thread(new Runnable() {
            @Override
            public void run() {

            }
        }).start();*/
//1.3 Lambda表达式
        //Runnable runnable = ()->{};
        //new Thread(runnable).start();
        new Thread(()->{
           while(true){
               try {
                   //等待客户端连接
                   Socket socket = serverSocket.accept();
                   sockets.add(socket);
                   //此处对于每一个客户端应该要有一个接收线程
                   //此处线程会有浪费,如果有N个客户端，会浪费N个无用线程
                   new ReceiveFileThread(socket).start();
                   //System.out.println(socket.getRemoteSocketAddress()+"连接成功!!!");
               } catch (IOException e) {
                   e.printStackTrace();
               }
           }
        }).start();
        //2、主线程发送命令
        Scanner scanner = new Scanner(System.in);
        while(true){
            System.out.println("请输入控制命令....");
            String cmd = scanner.nextLine();
            //群发给所有客户端
            sendToAll(cmd,sockets);
        }
    }

    private static void sendToAll(String cmd, CopyOnWriteArrayList<Socket> sockets) {
        for(Socket socket:sockets){
            //群发消息应该多线程发送,避免某一个
            new Thread(){
                @Override
                public void run() {
                    try {
                        DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
                        outputStream.writeUTF(cmd);
                    } catch (IOException e) {
                        //e.printStackTrace();
                        sockets.remove(socket);
                    }
                }
            }.start();
        }
    }
}

/**
 * 接收文件的线程
 */
class ReceiveFileThread extends Thread{
    private final String DIR_PATH = "d:\\network";
    private Socket socket;
    private DataInputStream dataInputStream;

    public ReceiveFileThread(Socket socket) throws IOException {
        this.socket = socket;
        dataInputStream = new DataInputStream(socket.getInputStream());
    }

    @Override
    public void run() {
        BufferedOutputStream bufferedOutputStream = null;
        try {
            //获取文件名称
            String fileName = dataInputStream.readUTF();
            //System.out.println(fileName);
            String[] subStr = fileName.split("\\.");
            //System.out.println(Arrays.toString(subStr));
            if(subStr.length<=1){
                return;
            }
            //abc.txt   abc  txt
            String fileType = subStr[subStr.length-1];
            //文件路径 DIR_PATH+客户端IP地址+文件名称
           InetSocketAddress socketAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
           String ipAddress =socketAddress.getAddress().getHostAddress();
           //文件要保存的绝对路径
           String filePath = DIR_PATH+File.separator+ipAddress+File.separator+fileType+File.separator+fileName;
            //System.out.println(filePath);
           //文件所在的文件夹
           File dirFilePath = new File(DIR_PATH+File.separator+ipAddress+File.separator+fileType);
            //System.out.println(dirFilePath);
           //根据文件扩展名存放文件
           //判断文件夹是否存在
           if(!dirFilePath.exists()){
               //不存在创建
               dirFilePath.mkdirs();
           }
            //循环读取文件内容
            byte[] buf = new byte[1024];
           int length = dataInputStream.read(buf);
           bufferedOutputStream =
                    new BufferedOutputStream(new FileOutputStream(filePath));
           while(length != -1){
               bufferedOutputStream.write(buf,0,length);
               length = dataInputStream.read(buf);
           }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                dataInputStream.close();
                bufferedOutputStream.flush();
                bufferedOutputStream.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
